package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Autowired
    private VodConstantProperties vodConstantProperties;
    // 云点播Api
    @Autowired
    private VodService vodService;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;


    /**
     * 上传声音
     *
     * @return
     */
    @Override
    public Map<String, Object> uploadTrack(MultipartFile file) {
        //	1. 创建一个上传客户端对象
        VodUploadClient client = new VodUploadClient(
                vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
        //	2. 构建上传路径
        VodUploadRequest request = new VodUploadRequest();
        String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
        request.setMediaFilePath(tempPath);
        //	3. 调用上传方法 -> client.upload()
        try {
            VodUploadResponse response = client.upload(vodConstantProperties.getRegion(), request);
            log.info("Upload filed = {}", response.getFileId());
            //	3.1 设置一个map；存储流媒体文件Id 以及 url路径
            HashMap<String, Object> map = new HashMap<>();
            map.put("mediaFileId", response.getFileId());
            map.put("mediaUrl", response.getMediaUrl());
            //	3.2 返回数据
            return map;
        } catch (Exception e) {
            // 3.3 业务方进行异常处理
            log.error("Upload Err = {}", e.getMessage());
        }
        //	4. 默认返回
        return new HashMap<>();
    }

    /**
     * 保存声音
     *
     * @param albumInfo
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId) {
        // 1.track_info
        TrackInfo trackInfo = new TrackInfo();
        // 2.属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        // 3.获取用户id
        trackInfo.setUserId(userId);
        // 4.rder_num 声音的序号
        //   根据专辑Id获取到专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());

        //	赋值流媒体相关字段数据 media_duration 、media_file_id 、media_size 、media_type，
        //	可以调用云点播的api获取！
        TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        trackInfo.setMediaDuration(mediaInfo.getDuration());
        trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
        trackInfo.setMediaSize(mediaInfo.getSize());
        trackInfo.setMediaType(mediaInfo.getType());
        //	保存声音
        trackInfoMapper.insert(trackInfo);

        //  声音统计初始化 track_stat;
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

        //  更新专辑对应的声音总数;
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() + 1);
        this.albumInfoMapper.updateById(albumInfo);
    }

    /**
     * 查看声音专辑列表
     *
     * @param page
     * @param trackInfoQuery
     * @return
     */
    @Override
    public IPage<TrackListVo> getUserTrackPage(Page<TrackListVo> page, TrackInfoQuery trackInfoQuery) {
        //调用mapper层方法
        return trackInfoMapper.selectUserTrackPage(page, trackInfoQuery);
    }

    /**
     * 根据声音Id回显数据
     *
     * @param trackId
     * @return
     */
    @Override
    public TrackInfo getTrackInfo(Long trackId) {
        return trackInfoMapper.selectById(trackId);
    }

    /**
     * 获取专辑声音分页列表
     *
     * @param albumTrackListVoPage
     * @param albumId
     * @param userId
     * @return
     */
    @Override
    public IPage<AlbumTrackListVo> getAlbumTrackPage(
            Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
        //  先获取当前专辑对应声音列表！
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(albumTrackListVoPage, albumId);
        //  主要设置是否需要付费字段 isShowPaidMark;
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);
        //  判断当前用户是否登录
        if (null == userId) {
            //  说明未登录！需要设置当前试听的声音免费 isShowPaidMark = false，其他声音收费 isShowPaidMark = true;
            if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
                //  先找到免费试听的集数; 先找到专辑对象;
                Integer tracksForFree = albumInfo.getTracksForFree();
                //  select * from track_info where order_num > 5 and album_id = 1429;
                pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
            // 返回数据
            return pageInfo;
        } else {
            //  用户已登录
            //  获取到当前用户对象
            Result<UserInfoVo> userInfoVoResult = this.userInfoFeignClient.getUserInfoVo(userId);
            //  获取数据
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            //  声明一个字段;
            boolean isNeedPaidMark = false;
            //  说明用户登录; 判断当前专辑的类型;
            if (SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //  判断当前专辑是vip免费; 判断当前用户是否是vip; is_vip字段;
                if ((1 == userInfoVo.getIsVip() && userInfoVo.getVipExpireTime().before(new Date())) || userInfoVo.getIsVip() == 0) {
                    isNeedPaidMark = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //  当前专辑是付费类型
                isNeedPaidMark = true;
            }

            //  统一处理付费情况：
            if (isNeedPaidMark) {
                //  除去用户购买的专辑或购买的声音之外{user_paid_album，user_paid_track}，要付费！
                //  获取需要付费的声音Id 列表;
                List<AlbumTrackListVo> trackListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo ->
                        albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).toList();
                List<Long> trackIdNeedPaidList = trackListVoList.stream().map(AlbumTrackListVo::getTrackId).toList();
                //  远程调用
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdNeedPaidList);
                // 获得数据
                Assert.notNull(mapResult, "付费声音结果集为空");
                //  map.put(trackId,1): 当前声音已购买，map.put(trackId,0): 当前声音未购买
                Map<Long, Integer> map = mapResult.getData();
                //  循环遍历
                for (AlbumTrackListVo albumTrackListVo : trackListVoList) {
                    //  设置当前声音是否需要付费;
                    //                    if (map.get(albumTrackListVo.getTrackId()) == 1) {
                    //                        albumTrackListVo.setIsShowPaidMark(false);
                    //                    } else {
                    //                        albumTrackListVo.setIsShowPaidMark(true);
                    //                    }
                    //  代码优化：
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 1 ? false : true);
                }
            }
        }
        //返回数据
        return pageInfo;
    }

    /**
     * 修改声音
     *
     * @param trackId
     * @param trackInfoVo
     * @return
     */
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {
        //  区分是否修改了当前的音频文件!
        //  根据声音Id 获取到 声音对象
        TrackInfo trackInfo = this.getById(trackId);
        //  原生声音对象; trackInfo.getMediaFileId();
        String oldMediaFileId = trackInfo.getMediaFileId();
        //  属性拷贝;
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //  最新的文件Id; trackInfoVo.getMediaFileId();
        if (!oldMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //  说明当前音频文件被修改了！ 重新计算当前声音的大小，类型，url，时长;
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
            //  赋值最新数据;
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaDuration(mediaInfo.getDuration());
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaType(mediaInfo.getType());
            //  云点播中的数据就要删除.
            vodService.removeMedia(oldMediaFileId);
        }
        //  更新数据
        this.updateById(trackInfo);
    }

    /**
     * 根据声音Id删除声音
     *
     * @param trackId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfoById(Long trackId) {
        //  先获取到专辑对象;
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        //  track_info is_deleted = 1;
        trackInfoMapper.deleteById(trackId);
        //  track_stat is_deleted = 1;
        trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId, trackId));
        //  album_info.include_track_count-1;
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //  修改包含声音总数
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        //  更新专辑最新数据
        albumInfoMapper.updateById(albumInfo);
        //  声音对应的order_num 应该-1;
        //  update track_info set order_num = order_num - 1 where order_num > 51 and album_id = 1 and is_deleted = 0;
        trackInfoMapper.updateOrderNum(trackInfo.getOrderNum(), albumInfo.getId());
        //  删除云点播中的数据:
        vodService.removeMedia(trackInfo.getMediaFileId());
    }

    /**
     * 声音初始化
     *
     * @param id
     * @param trackStatPlay
     */
    private void saveTrackStat(Long trackId, String statPlay) {
        //  创建声音统计对象
        TrackStat trackStat = new TrackStat();
        //  赋值：
        trackStat.setTrackId(trackId);
        trackStat.setStatType(statPlay);
        trackStat.setStatNum(new Random().nextInt(1000));
        this.trackStatMapper.insert(trackStat);
    }
}
